using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Security.Permissions;

namespace GameEditor.Common.Controls
{
    public enum TogglePolicy
    {
        Pressing,
        GroupCheck,
        Standalone,
    }

    public class ToggleButton : ButtonBase, IGroupElement
    {
        public event EventHandler OnCheckChanged = delegate { };
        private bool _checked = false;
        private bool _pressedDown = false;
        private ControlGroup controlGroup;
        private StringFormat format = new StringFormat();
        private Pen selectedBorder = new Pen(Color.Gray);
        [Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
        public ControlGroup ControlGroup
        {
            get { return controlGroup; }
            set 
            {
                controlGroup = value;
            }
        }
        private TogglePolicy togglePolicy = TogglePolicy.Pressing;

        public TogglePolicy TogglePolicy
        {
            get 
            {
                if (controlGroup != null)
                    return TogglePolicy.GroupCheck;
                return togglePolicy; 
            }
            set 
            {
                if (value == TogglePolicy.GroupCheck)
                    return;
                togglePolicy = value; 
            }
        }

        private DialogResult dialogResult = DialogResult.None;

        public DialogResult DialogResult
        {
            get { return dialogResult; }
            set { dialogResult = value; }
        }


        public bool Checked
        {
            get 
            {
                if (TogglePolicy == TogglePolicy.GroupCheck && controlGroup!=null)
                    return controlGroup.ActiveElement == this;
                return _checked; 
            }
            set
            {
                _checked = value;
                if (TogglePolicy == TogglePolicy.GroupCheck)
                {
                    _pressedDown = _checked;
                    if (controlGroup != null && controlGroup.ActiveElement != this && value )
                        controlGroup.ActiveElement = this;
                }
                if (TogglePolicy == TogglePolicy.Standalone)
                    _pressedDown = _checked;
                if (IsHandleCreated)
                    Invalidate();
            }
        }

        public ToggleButton()
        {
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            selectedBorder.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
        }


        protected override void Dispose(bool disposing)
        {
            format.Dispose();
            selectedBorder.Dispose();
            base.Dispose(disposing);

        }
        protected override void OnPaint(PaintEventArgs pevent)
        {
            Graphics g = pevent.Graphics;
            Size size = this.Size;
            Rectangle rect = new Rectangle(0, 0, size.Width - 1, size.Height - 1);

            g.FillRectangle(Brushes.Gainsboro, rect);

            Pen p1 = Pens.White;
            Pen p2 = Pens.Gray;
            if (_pressedDown)
            {
                p1 = Pens.Gray;
                p2 = Pens.White;
            }
            g.DrawLine(p1, rect.Left, rect.Top, rect.Left, rect.Bottom);
            g.DrawLine(p1, rect.Left, rect.Top, rect.Right, rect.Top);
            g.DrawLine(p2, rect.Right, rect.Bottom, rect.Left, rect.Bottom);
            g.DrawLine(p2, rect.Right, rect.Bottom, rect.Right, rect.Top);
            if (Focused)
            {
                Rectangle selectedRect = new Rectangle(3, 3, size.Width - 7, size.Height - 7);
                g.DrawRectangle(selectedBorder, selectedRect);
            }

            if (Image != null)
            {
                Image img = Image;

                System.Drawing.Imaging.ImageAttributes attr;
                attr = new System.Drawing.Imaging.ImageAttributes();
                attr.SetColorKey(Color.Black, Color.Black);
                Rectangle r = new Rectangle(rect.X + (rect.Width - img.Width) / 2, rect.Y + (rect.Height - img.Height) / 2, img.Width, img.Height);
                g.DrawImage(Image, r,0,0,img.Width,img.Height,GraphicsUnit.Pixel, attr);
            }

            string text = Text;
            if (!string.IsNullOrEmpty(text))
            {
                if(Enabled)
                    g.DrawString(text, Font, Brushes.Black, rect, format);
                else
                    g.DrawString(text, Font, Brushes.Gray, rect, format);
            }

        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            if(TogglePolicy==TogglePolicy.Pressing) 
            {
                _pressedDown = true;
                Invalidate();
            }
            base.OnMouseDown(mevent);
        }
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            if (TogglePolicy==TogglePolicy.Pressing) 
            {
                _pressedDown = false;
                Invalidate();
            }
            base.OnMouseUp(mevent);
        }


        protected override void OnClick(EventArgs e)
        { 
            bool old_state = _checked;

            if (TogglePolicy==TogglePolicy.GroupCheck && controlGroup != null && controlGroup.ActiveElement != this)
            {
                
                controlGroup.ActiveElement = this;

                _checked = _pressedDown = controlGroup.ActiveElement == this;
            }
            if (TogglePolicy == TogglePolicy.Standalone)
            {
                _checked=!_checked;
                _pressedDown=_checked;
            }

            base.OnClick(e);
            if (old_state != _checked)
            {
                OnCheckChanged(this, EventArgs.Empty);
                Invalidate();
            }

            if (dialogResult != DialogResult.None && Parent != null && Parent is Form)
            {
                (Parent as Form).DialogResult = dialogResult;
            }

        }
    }
}
